עוד גרסה שמטפלת בבאג אבטחה קריטי יצאה. דיברנו כבר על זה שכל גרסאות ה-PHP עד 5.3.9 חשופות למתקפת DOS שעשויה להוריד את השרת, אם כי התיקון שסגר את החור ב-5.3.9 פתח חור חדש. כל המידע מתחת לקאט.
אחד "החידושים" של גרסת 5.3.9 היה הכנסת פרמטר חדש שמגביל את כמות משתני ה-POST שהשרת יהיה מוכן לקבל כדי למנוע את מתקפת ה-Hash Collision DoS שיכולה להביא לניצול 100% מעבד והפסקת פעולת השרת.
יחד עם זאת, לקוד שמטפל בבעיה הזו התגנבה טעות שמאפשרת להפעיל קוד זדוני שרירותי בשרת.
הפרצה התגלתה על ידי מומחה לנושאי הבטחה סטפן אססר, הידוע בזכות מציאת כמה בעיות אבטחה קריטיות ב-PHP ויצירת jail break למערכות iOS.
הפונקציה הנגועה
php_register_variable_ex (php_variables.c@194)
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
{
/* ... */
if (is_array) {
/* ... */
while (1) {
/* ... */
if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
}
MAKE_STD_ZVAL(gpc_element);
array_init(gpc_element);
zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
}
/* ... */
symtable1 = Z_ARRVAL_PP(gpc_element_p);
/* ... */
{
/* ... */
if (is_array) {
/* ... */
while (1) {
/* ... */
if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
}
MAKE_STD_ZVAL(gpc_element);
array_init(gpc_element);
zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
}
/* ... */
symtable1 = Z_ARRVAL_PP(gpc_element_p);
/* ... */
ההגבלה על כמות הפרמטרים ממומשת על ידי לולאה ותנאי IF, אבל בלי ELSE שאמור לגרום ללולאה להפסיק. בעקבות זאת, ביציאה מהלולאה למאקרוס Z_ARRVAL_PP, שמחזיר מצביע לטבלת החאשים החדשה, נכנס אלמנט נוסף (gpc_elemnt_p) עם הערך של המשתנה האחרון שטופל בלולאה. מה שמוביל להפעלת הקוד.
שרתים עם ההרחבה suhosin לא מושפעים מהבעיה (המפתח של suhosin patch זה סטפן עצמו, אגב).
מצחיק שיום לפני כן, החליטה debin להוציא את suhosin patch מההתקנה הדיפולטית.
phpguide כבר אתמול עבר ל-5.3.10.
העידכון הינו חובה לכל בעלי השרתים הנגישים באופן פומבי. אם השרת שלכם משמש אתכם רק לפיתוח ב-localhost אתם יכולים להישאר רגועים.
תגובות לכתבה:
למה שלא לשים את תנאי היציאה כבר בתנאי של הלולאה?
בכל אופן, תודה רבה ותוסיף את זה לכאן:
http://phpguide.co.il/PHP 539.htm
הייתי מנסה לענות לך, אבל זה הרבה מעבר לרמה שלי :) כנראה שזה פשוט טעות והוא שכח ממנה.
אני גם לא מבין למה לא להוציא את התוצאה של
PG(max_input_vars)
למשתנה אחד מחוץ ללולאה.
while(1)
ממש נראה קוד שכונה :)
חח, מצחיק אבל זה ככה. הקוד מקור של PHP באמת שכונה, זו עובדה ידועה :)
לא ממש שכונה... זה קוד C, מתרגלים לזה אבל ככה קוד באמת צריך להיראות ובשלב מסויים... מתחברים אליו יותר (מעדיף CPP, אבל נניח את זה בצד).
@iiddaannyy אני לא רואה פה את השינויי שדובר עליו בכתבה (את התנאי ELSE) אז קשה לי לענות לך, תקן אותי אם אני טועה.
@intval - בגלל שPG זה מאקרו, תבניות מאקרו ב-C הן תבניות שמוחלפות לערך שלהן *לפני* הקימפול, ולכן אין הבדל ממשי (כמובן שהכול תלוי בערך המאקרו, לא התעמקתי יותר מדי בAPI עצמו ולכן אשאיר את זה בצד ואסמוך על התוכניתן שידע מה לעשות חחח)
דוגמא לצורך העניין:
[code]
#import <stdin>
// Define new macro
#define ADD(a, b) (a + b)
int main() {
printf("%d", ADD(1, 2));
// is the same as:
// printf("%d", (1+2));
return 0;
}
[/code]
מעניין, תודה, על ההסבר.
הלכתי לנסות.
@משתמש_106504
התכוונתי לכך שאת תנאי היצאה של הלולאה אפשר לשים בתנאי של הלולאה, בסוגריים שליד ה-while, במקום לגרום ללולאה לרוץ שוב ושוב ושהקוד שבתוכה יעצור אותה כשצריך.
ואמרתי שכדאי להוסיף לכאן: http://phpguide.co.il/PHP 539.htm
שכדאי להוריד את גירסה 5.3.10 אם כבר משדרגים.
אני חושב שאנחנו צריכים לזכור שזאת שפה , ולא כל קטע קוד שנראה לנו "שכונה" הוא כזה.
אני מאמין שיש מחשבה מאחורי זה.
אני ידמה את זה למשהו אחר :
ברגע שאתה רואה קובץ למשל מתוך מערכת שאתה לא מכיר ורואה שם דברים שלא נראים לך , אתה לא באמת יכול לשפוט את זה לפני שתעבור על כל המערכת ותראה למה זה נכתב ככה , כנראה יש סיבה למה השתמשו בדרך מסוימת ולא בדרך אחרת.
אם תמיד היו חושבים כל כך הרבה לפני שהיו כותבים,
לא היו באגים,
ופלא.. באגים תמיד היו ויהיו